package io.inputstream ;

import java.io.BufferedInputStream ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.IOException ;
import java.io.InputStream ;

/**
 * 测试bufferedinputstream的缓冲功能，以及标记重设的功能 Description:
 * 
 * @author 80002165
 * @date 2017年1月11日 上午9:18:32
 */
public class TestBufferedInputStream {
    public static void main(String[] args) {
        testBuffer() ;
        testMarkReset() ;
    }
    
    /**
     * BufferedInputStream是一个具有缓冲功能的输入流会一次性将缓冲大小的数据读入到流内
     * 1、如果没有设置缓冲流的大小，java默认的给了一个大小为： private static int DEFAULT_BUFFER_SIZE = 8192;
     * 2、如果缓冲区内的数据没有读完，BufferenInputStream不会再将数据写入到流内，而是等缓冲区的数据读完，再一次性读取等于或小于
     * （数据已读完）缓冲大小的数据 从下面的程序可以看出：BufferedInputStream设置缓冲区大小为8字节，每次读取数据位4字节，一次并不能将所有的数据读完，
     * 所以BufferedInputStream把数据写了两次到byte数组cache后才再想InputStream:in读取两外8个字节的数据。
     * 从BufferedInputStream的特点可以看出，似乎我们应该讲BufferedInputStream的缓冲区设的越大，那么对于提高我们IO读写的效率越有效，
     * 但是不要忘记，效率（时间成本）和内存大小本是一对相互平衡制约的资源利用关系。只有考虑到实际情况，平衡两者关系，才能使系统效率达到最大化
     * @author 80002165
     * @date 2017年1月11日 上午9:34:24
     */
    private static void testBuffer() {
        int readSize = 4 ;
        InputStream in = null ;
        BufferedInputStream bufferIn = null ;
        try {
            // bufferIn = new BufferedInputStream(in) ;
            in = new FileInputStream("e:/testBufferedInputstream.txt") ;
            bufferIn = new BufferedInputStream(in, 2*readSize) ;
            byte[] cache = new byte[readSize] ;
            int length = bufferIn.available() ;
            System.out.println("bufferIn.length:" + length) ;
            System.out.println("in.length:" + in.available()) ;
            System.out.println("----------------------------------") ;
            int temp = 0 ;
            StringBuilder result = new StringBuilder() ;
            while ((temp = bufferIn.read(cache)) != -1) {
                result.append(new String(cache, 0, temp, "utf-8")) ;
                System.out.println("每次读取的字节数：" + temp) ;
                System.out.println("bufferedInputstream中剩下的字节数：" + bufferIn.available()) ;
                System.out.println("inputstream中剩下的字节数：" + in.available()) ;
                System.out.println("----------------------------------") ;
                /* print结果：
                 * bufferIn.length:157 
                 * in.length:157
                 * ---------------------------------- 
                 * 每次读取的字节数：4
                 * bufferedInputstream中剩下的字节数：153 
                 * inputstream中剩下的字节数：149
                 * ---------------------------------- 
                 * 每次读取的字节数：4
                 * bufferedInputstream中剩下的字节数：149 
                 * inputstream中剩下的字节数：149
                 * ----------------------------------
                 * ......
                 */
            }
            System.out.println(result.toString()) ;
        } catch (Exception e) {
            e.printStackTrace() ;
        } finally {
            if (in != null) {
                try {
                    in.close() ;
                } catch (IOException e) {
                    e.printStackTrace() ;
                }
            }
            if (bufferIn != null) {
                try {
                    bufferIn.close() ;
                } catch (IOException e) {
                    e.printStackTrace() ;
                }
            }
        }
    }
    
    /**
     * BufferedInputStream是javaIO流里面为数不多的支持标记和重设的流。所以如果需要使用到io流的这个功能，必须要先调用markSupported方法，查看流是否支持这项功能
     * 1、调用mark方法标记流读取的位置，需要注意的是，该方法有一个整型参数，该参数大小为“可以读取的最大字节数”并且该参数不可小于剩下的流中的字节数，否则在调用reset方法时，会抛异常：java.io.IOException: Resetting to invalid mark
     * 2、在设置mark的readlimit数值时，如果是BufferedInputStream应该注意值应该大于或等于：in.available()+bufferIn.available()，因为剩下的数据在原来的输入流中还有，而BufferedInputStream中，也可能存在未读取的字节。
     * @author 80002165
     * @date 2017年1月11日 上午10:47:33
     */
    private static void testMarkReset(){
        int readSize = 25 ;
        InputStream in = null ;
        BufferedInputStream bufferIn = null ;
       
        try {
            in = new FileInputStream("e:/testBufferedInputstream.txt") ;
            bufferIn = new BufferedInputStream(in, 2*readSize) ;
            byte[] cache = new byte[readSize] ;
            int temp = 0 ;
            StringBuilder result = new StringBuilder() ;
            System.out.println("BufferedInputStream是否可以标记重设："+bufferIn.markSupported()) ;
            int flag = 0 ;
            while(( temp = bufferIn.read(cache)) != -1){
                if(flag ==0 && bufferIn.markSupported()){
                    bufferIn.mark(in.available()+bufferIn.available());
                }
                result.append(new String(cache,0,temp)) ;
                flag++ ;
            }
            result.append("\nend\n") ;
            bufferIn.reset();
            //重设后再度
            while(( temp = bufferIn.read(cache)) != -1){
                result.append(new String(cache,0,temp)) ;
            }
            System.out.println(result.toString()) ;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /* print结果：
     * asdfsdfsdfwerwerssdfewewr445455asdfsdfsdfasdf22a2sdfwerweqrweqrweqrwqer
     * sdfsdiesdfew12309asfqwerwerwpasdf
     * ...asdfoewermasfooasd;f;lemreq;asdfdsfaasdfqwerpi;jjv alsdifjeipqiwue
     * ralskdjf %*&*��������@#��@��%% 
     * end
     * 445455asdfsdfsdfasdf22a2sdfwerweqrweqrweqrwqer
     * sdfsdiesdfew12309asfqwerwerwpasdf
     * ...asdfoewermasfooasd;f;lemreq;asdfdsfaasdfqwerpi;jjv alsdifjeipqiwue
     * ralskdjf %*&*��������@#��@��%%
     */
    
}
